﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PSE.ProcessManager.Client.Process;
using PSE.ProcessManager.Common.Gateway;
using Sinacor.Infra.Common.Exceptions.FaultContracts;
using System.ServiceModel;
using Sinacor.Infra.Common.Security.Authentication.ClientCredentials;
using Sinacor.Infra.Common.Security.Cryptography;
using Sinacor.Infra.UI.Common;
using System.Security.Cryptography.X509Certificates;
using Sinacor.Infra.Common.Security.Authentication.Credentials;
using PSE.Framework.Configuration;
using PSE.ProcessManager.Common.Configuration;

namespace Sinacor.Infra.Core.ProcessManager.Client
{
    public class SinacorBaseProcessClient : BaseProcess
    {
        /// <summary>
        /// Construtor da classe.
        /// </summary>
        public SinacorBaseProcessClient()
            : base()
        {
            this.ProductId = "Sinacor";
            base._inteligenceManagerGateway.TokenParameters = new SinacorTokenParameters();
        }

        /// <summary>
        /// Construtor da classe.
        /// </summary>
        public SinacorBaseProcessClient(int id)
            : base(id)
        {
            this.ProductId = "Sinacor";
            base._inteligenceManagerGateway.TokenParameters = new SinacorTokenParameters();
        }

        protected override void OnMessageReceived(BaseMessage message)
        {
            switch (message.MessageId)
            {
                case _errorMessageId:
                    this.ThrowProcessException(HandleException(message));
                    break;

                default:
                    base.OnMessageReceived(message);
                    break;
            }
        }

        private Exception HandleException(BaseMessage message)
        {
            switch (message.ParameterType)
            {
                case "BusinessFault":
                    return message.RetrieveParameter<BusinessFault>().CreateException().CreateFaultException();
                case "ValidationFault":
                    return message.RetrieveParameter<ValidationFault>().CreateException().CreateFaultException();
                case "AccessIsDeniedFault":
                    return message.RetrieveParameter<AccessIsDeniedFault>().CreateException().CreateFaultException();
                case "InvalidSessionFault":
                    return message.RetrieveParameter<InvalidSessionFault>().CreateException().CreateFaultException();
                case "LicensingFault":
                    return message.RetrieveParameter<LicensingFault>().CreateException().CreateFaultException();
                case "GeneralFault":
                    return message.RetrieveParameter<GeneralFault>().CreateException().CreateFaultException();
                
                case "string":
                    return new FaultException(message.RetrieveParameter<string>());
                default:
                    return new Exception(string.Format("Unknow parameter type '{0}'", message.ParameterType));
            }
        }

        /// <summary>
        /// Define as credenciais do usuário para autenticação no Process Manager.
        /// </summary>
        /// <param name="loginName">Login do usuário</param>
        /// <param name="password">Password do usuário</param>
        public void SetUserCredentials(string loginName, string password, int companyId)
        {
            SessionInformation si = new SessionInformation(false);
            si.LoginName = loginName;
            si.Password = password;
            si.CompanyId = companyId;
            this.SetUserCredentials(si);
        }

        /// <summary>
        /// Define as credenciais do usuário para autenticação no Process Manager.
        /// </summary>
        /// <param name="sessionInformation"></param>
        public void SetUserCredentials(SessionInformation sessionInformation)
        {
            SinacorClientCredentials credentials = new SinacorClientCredentials();

            string tokenId = string.IsNullOrEmpty(sessionInformation.TokenId) ? Guid.NewGuid().ToString() : sessionInformation.TokenId;

            credentials.UserInfo = new SinacorUserInfo(sessionInformation.LoginName,
                                                        sessionInformation.Password,
                                                        sessionInformation.CompanyId,
                                                        sessionInformation.Id,
                                                        tokenId,
                                                        false);

            credentials.ServiceCertificate.SetDefaultCertificate("CN=SinacorSTSAuthority", StoreLocation.LocalMachine, StoreName.TrustedPeople);
            credentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.PeerOrChainTrust;

            base.SetUserCredentials(credentials);
        }
    }
}
